#ifndef __IIC_C
#define __IIC_C

#include "IIC.h"

uint8_t I2C_error_code = 0;
DMA_Config_T dmaConfig;

void IIC_Pin_init(){
	  GPIO_Config_T  configStruct;
	  RCM_EnableAPB2PeriphClock(IIC2_PIN_RTC);
	  RCM_EnableAPB2PeriphClock(IIC2_PinAF_RTC);
	  
	  // I2C_SDA
 	  configStruct.mode = GPIO_MODE_AF_OD;
	  configStruct.speed = GPIO_SPEED_50MHz;
	  configStruct.pin = IIC2_SDA_PinId;
	  GPIO_Config(IIC2_PinPort, &configStruct);
	  // I2C_SCL
	  configStruct.mode = GPIO_MODE_AF_OD;
	  configStruct.speed = GPIO_SPEED_50MHz;
	  configStruct.pin = IIC2_SCL_PinId;
	  GPIO_Config(IIC2_PinPort, &configStruct);
	
}

void IIC_init(){	 
   I2C_Config_T i2cConfigStruct;
   RCM_EnableAPB1PeriphClock(IIC_RTC);
   I2C_Reset(IIC_ID);
	 
	 #ifndef AT32F403AVGT7
   i2cConfigStruct.mode = I2C_MODE_I2C;	 
	 #endif
	 i2cConfigStruct.dutyCycle = I2C_DUTYCYCLE_2; // IIC占空比: 2 = 低位 / 高位
   i2cConfigStruct.ackAddress = I2C_ACK_ADDRESS_7BIT; // 应答地址7位
	 // 设备写地址：
	 i2cConfigStruct.ownAddress1 = My_Addr; // 主机地址
	 #ifndef AT32F403AVGT7
   i2cConfigStruct.ack = I2C_ACK_ENABLE;  // I2C_ACK_ENABLE  
	 #endif
   i2cConfigStruct.clockSpeed = 100000;   // IIC速度 = 400K;IIC最高速
   I2C_Config(IIC_ID,&i2cConfigStruct);  

	 // 开启DMA功能：
	 I2C_EnableDMA(IIC_ID);
	
   /* Enable I2Cx */
   I2C_Enable(IIC_ID);
}

// IIC-DMA初始化配置
void I2C_TX_DMA_Init(){
    RCM_EnableAHBPeriphClock(IIC2_DMA_RTC);

	  DMA_Reset(IIC_DMA_TX_Channel);  
    dmaConfig.peripheralBaseAddr = IIC_TX_ADDRESS;  
	  dmaConfig.memoryBaseAddr = (uint32_t)NULL; // 内存起始地址=null;初始内存地址不设置;
    dmaConfig.dir = DMA_DIR_PERIPHERAL_DST; // 内存到IIC外设
    dmaConfig.bufferSize = 0;  
    dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;   
    dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;  
    dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_BYTE;  
    dmaConfig.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE;  
    dmaConfig.loopMode = DMA_MODE_NORMAL; // 单次数据传递,传递完bufferSize个数据,就结束。   
    dmaConfig.priority = DMA_PRIORITY_HIGH; // DMA_PRIORITY_HIGH = DMA优先级高。
	
    #ifndef AT32F403AVGT7	
    dmaConfig.M2M = DMA_M2MEN_DISABLE;  
    #endif
	
		// DMA通道使能
    DMA_Config(IIC_DMA_TX_Channel, &dmaConfig);
}

// DMA重配置：
void i2c_dma_config(uint8_t* pdata, uint16_t size){
		// 关闭通道
		dma_channel_enable(IIC_DMA_TX_Channel, FALSE);
    // 关闭传输通道
		dma_interrupt_enable(IIC_DMA_TX_Channel,DMA_FDT_INT, FALSE);
    // 配置缓冲地址和缓存大小
		dmaConfig.memory_base_addr     = (uint32_t)pdata;
		dmaConfig.direction            =  DMA_DIR_MEMORY_TO_PERIPHERAL;
		dmaConfig.peripheral_base_addr = IIC_ID -> dt;
		dmaConfig.buffer_size          = (uint32_t)size;
		dma_init(IIC_DMA_TX_Channel,&dmaConfig);
    // 使能DMA中断
		dma_interrupt_enable(IIC_DMA_TX_Channel,DMA_FDT_INT, TRUE);
    // 使能DMA通道
		dma_channel_enable(IIC_DMA_TX_Channel, TRUE);
}


//等待某个标志，并处理异常事件：只有event_check=I2C_EVENT_CHECK_NONE是等待;其余则是判断。
// 本质等待3个事件：flag==1 / event_check=I2C_EVENT_CHECK_ACKFAIL 或 I2C_EVENT_CHECK_STOP / timeout
// flag = I2C的状态寄存器标志位值；event_check = 检测事件;
i2c_status_type i2c_wait_flag(uint32_t flag, uint32_t event_check, uint8_t timeout){
		if(flag == I2C_BUSYF_FLAG){  
			  // I2C总线忙标志：总线不忙就跳出等待，或超时跳出等待。
				while(i2c_flag_get(IIC_ID, flag) != RESET){  // 等待 I2C_BUSYF_FLAG == 1
					  // 等待超时
						if((timeout--) == 0){
								I2C_error_code = I2C_ERR_TIMEOUT;
								return I2C_ERR_TIMEOUT;
						}
				}
		} else { 
			  // 其他的标志位：只有标志位 = 1，才能跳出等待。
			  // 或者出现某事件，超时也可以跳出等待。
				while(i2c_flag_get(IIC_ID, flag) == RESET){ 
						// I2C_EVENT_CHECK_ACKFAIL 出现NACK信号的处理;
						if(event_check & I2C_EVENT_CHECK_ACKFAIL){
							  // 检测非应答信号NACK：一旦检出，停止通讯
								if(i2c_flag_get(IIC_ID, I2C_ACKFAIL_FLAG) != RESET){ // I2C_ACKFAIL_FLAG == 1
										// 停止位
										i2c_stop_generate(IIC_ID);
										// 清除应答位
										i2c_flag_clear(IIC_ID, I2C_ACKFAIL_FLAG);
										// 应答错误
										I2C_error_code = I2C_ERR_ACKFAIL;
										return I2C_ERR_ACKFAIL;
								}
						}
						// 停止事件检测：是否有发出停止位的事件
						if(event_check & I2C_EVENT_CHECK_STOP){
								if(i2c_flag_get(IIC_ID, I2C_STOPF_FLAG) != RESET){
										// 有停止事件：清除停止标志位
										i2c_flag_clear(IIC_ID, I2C_STOPF_FLAG);
										I2C_error_code = I2C_ERR_STOP;
										return I2C_ERR_STOP;
								}
						}
						// 等待超时
						if((timeout--) == 0){
								I2C_error_code = I2C_ERR_TIMEOUT;
								return I2C_ERR_TIMEOUT;
						}
				}
		}
		return I2C_OK;
}


// 主模式：发送写地址
i2c_status_type i2c_master_write_addr(uint16_t address, uint8_t timeout){
		// 起始位开始
		i2c_start_generate(IIC_ID);
		// 等待起始位标志
		if(i2c_wait_flag(I2C_STARTF_FLAG, I2C_EVENT_CHECK_NONE, timeout) != I2C_OK){
				I2C_error_code = I2C_ERR_START;
				return I2C_ERR_START;
		}
		// 发送地址数据
		if(IIC_ID->oaddr1_bit.addr1mode == I2C_ADDRESS_MODE_7BIT){
				// 发送7位从设备地址：
				i2c_7bit_address_send(IIC_ID, address, I2C_DIRECTION_TRANSMIT);
		} else {
				// 发送10位地址头部
				i2c_data_send(IIC_ID, (uint8_t)((address & 0x0300) >> 7) | 0xF0);
			  // 等待回应
				if(i2c_wait_flag(I2C_ADDRHF_FLAG, I2C_EVENT_CHECK_ACKFAIL, timeout) != I2C_OK){
					I2C_error_code = I2C_ERR_ADDR10;
					return I2C_ERR_ADDR10;
				}
        // 发送剩余的7位从设备地址  
				i2c_data_send(IIC_ID, (uint8_t)(address & 0x00FF));
		}
		// 等待地址发送成功EV2
		if(i2c_wait_flag(I2C_ADDR7F_FLAG, I2C_EVENT_CHECK_ACKFAIL, timeout) != I2C_OK){
			I2C_error_code = I2C_ERR_ADDR;
			return I2C_ERR_ADDR;
		}
		return I2C_OK;
}

// 主模式：发送读地址：
i2c_status_type i2c_master_read_addr(uint16_t address, uint8_t timeout){
		// 使能应答
		i2c_ack_enable(IIC_ID, TRUE);
		// 起始位
		i2c_start_generate(IIC_ID);
		// 等待开始信号
		if(i2c_wait_flag(I2C_STARTF_FLAG, I2C_EVENT_CHECK_NONE, timeout) != I2C_OK){
				I2C_error_code = I2C_ERR_START;
				return I2C_ERR_START;
		}
		// 发送设备地址
		if(IIC_ID->oaddr1_bit.addr1mode == I2C_ADDRESS_MODE_7BIT) {
				i2c_7bit_address_send(IIC_ID, address, I2C_DIRECTION_RECEIVE);
		}  else  {
			  // 发送10位地址头部
				i2c_data_send(IIC_ID, (uint8_t)((address & 0x0300) >> 7) | 0xF0);
        // 等待头部发送成功
				if(i2c_wait_flag(I2C_ADDRHF_FLAG, I2C_EVENT_CHECK_ACKFAIL, timeout) != I2C_OK){
					I2C_error_code = I2C_ERR_ADDR10;
					return I2C_ERR_ADDR10;
				}
        // 发送剩余的从设备地址
				i2c_data_send(IIC_ID, (uint8_t)(address & 0x00FF));
        // 等待7位地址发送成功   
				if(i2c_wait_flag(I2C_ADDR7F_FLAG, I2C_EVENT_CHECK_ACKFAIL, timeout) != I2C_OK) {
						I2C_error_code = I2C_ERR_ADDR;
						return I2C_ERR_ADDR;
				}
				// 清除地址标志
				i2c_flag_clear(IIC_ID, I2C_ADDR7F_FLAG);
        // 重新开始位
				i2c_start_generate(IIC_ID);
        // 等待开始位成功
				if(i2c_wait_flag(I2C_STARTF_FLAG, I2C_EVENT_CHECK_NONE, timeout) != I2C_OK){
						I2C_error_code = I2C_ERR_START;
						return I2C_ERR_START;
				}
        // 发送从设备10位地址头部：
				i2c_data_send(IIC_ID, (uint8_t)((address & 0x0300) >> 7) | 0xF1);
		}
    // 等待地址发送成功EV2
		if(i2c_wait_flag(I2C_ADDR7F_FLAG, I2C_EVENT_CHECK_ACKFAIL, timeout) != I2C_OK){
				I2C_error_code = I2C_ERR_ADDR;
				return I2C_ERR_ADDR;
		}
		return I2C_OK;
}

// 通过DMA发送数据：
i2c_status_type i2c_master_transmit_dma(uint16_t address, uint8_t* pdata, uint16_t size, uint8_t timeout){		
		I2C_error_code = I2C_OK;
    
	  // 等待总线空闲
		if(i2c_wait_flag(I2C_BUSYF_FLAG, I2C_EVENT_CHECK_NONE, timeout) != I2C_OK){
				return I2C_ERR_STEP_1;
		}
		// 失能ack位：
		i2c_master_receive_ack_set(IIC_ID, I2C_MASTER_ACK_CURRENT);
    // 失能DMA功能：
		i2c_dma_enable(IIC_ID, FALSE);
    // 重新配置DMA参数
		i2c_dma_config(pdata, size);
    // 主设备发送地址：
		if(i2c_master_write_addr(address, timeout) != I2C_OK){
				i2c_stop_generate(IIC_ID);
				return I2C_ERR_STEP_2;
		}
    // 清除地址标志位：
		i2c_flag_clear(IIC_ID, I2C_ADDR7F_FLAG);
    // 使能DMA传送：
		i2c_dma_enable(IIC_ID,TRUE);
		return I2C_OK;
}

// I2C的DMA搬运数据启动：buffer内存数据搬到I2C外设寄存器中，并发送出去;
void i2c_dma_transmit_buffer(unsigned char *buffer, unsigned int length){
	  i2c_master_transmit_dma(OLed_Tx_Addr, buffer, length, I2C_TimeOut);
}

// I2C向从设备OLed_Tx_Addr，写1个字节数据：适合写命令数据
// cmd == 1，则是发送一个指令；cmd == 0，发送数据;
void i2c_wr_byte(unsigned char byte,unsigned char cmd){
//		uint8_t ii = I2C_TimeOut;
//		// 产生起始信号
//		I2C_EnableGenerateStart(IIC2_ID);
//		// 等待EV5事件：检测起始信号是否成功
//		while((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_MODE_SELECT)) && ii){
//				ii--;
//		} 		
//		// 发送从设备地址
//		I2C_Tx7BitAddress(IIC2_ID, OLed_Tx_Addr, I2C_DIRECTION_TX);
//		// 检测EV6事件：等待从机地址是否发送完;
//		ii = I2C_TimeOut;
//		while ((!I2C_ReadEventStatus(IIC2_ID,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && ii){
//				ii--;
//		} 	   
//		// 数据寄存器地址,或指令寄存器地址：数据模式;			
//		if(cmd) 
//			 I2C_TxData(IIC2_ID, 0x00); 
//		else
//			 I2C_TxData(IIC2_ID, 0x40); 
//		// 检测EV8：等待数据是否发送完;
//		ii = I2C_TimeOut;
//		while ((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) && ii){
//				ii--;
//		}  
//		// 检测EV8_2；等待最后一个字节数据发送完; 
//		I2C_TxData(IIC2_ID, byte); 
//		ii = I2C_TimeOut;
//		while ((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) && ii){
//				ii--;
//		} 
//		// 发送停止信号
//		I2C_EnableGenerateStop(IIC2_ID);
			unsigned char buffer[2];
      if(cmd) buffer[0] = 0x00;
      else buffer[0] = 0x40;
      buffer[1] = byte;			
	    i2c_master_transmit_dma(OLed_Tx_Addr, buffer, 2, I2C_TimeOut);
}

// I2C向从设备OLed_Tx_Addr，写一个数组数据buffer，长度=length：适合写长数据
void i2c_write_buffer(unsigned char *buffer,unsigned int length){
//    uint8_t ii = I2C_TimeOut;	
//	  I2C_EnableGenerateStart(IIC2_ID);
//	  // EV5
//	  while((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_MODE_SELECT)) && ii){
//			  ii--;
//		}   
//	  I2C_Tx7BitAddress(IIC2_ID, OLed_Tx_Addr, I2C_DIRECTION_TX);
//	  // EV6
//		ii = I2C_TimeOut;
//		while((!I2C_ReadEventStatus(IIC2_ID,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && ii){
//			  ii--;
//		}  
//	  I2C_TxData(IIC2_ID, 0x40); 
//		// EV8
//		ii = I2C_TimeOut;
//	  while ((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) && ii){  
//			  ii--;
//		}  
//    i2c_dma_transmit_buffer(buffer,length);	 // DMA Transmit		
	    i2c_master_transmit_dma(OLed_Tx_Addr, buffer, length, I2C_TimeOut);
}

void I2C_Tx_DMAChanel_IRQHandler(){
		// 传输结束
		if(dma_flag_get(I2C_Tx_DMA_FLAG_TC) != RESET){
				dma_interrupt_enable(IIC_DMA_TX_Channel, DMA_FDT_INT, FALSE);				
				i2c_dma_enable(IIC_ID, FALSE);
				i2c_interrupt_enable(IIC_ID, I2C_EVT_INT, TRUE); 
				dma_flag_clear(I2C_Tx_DMA_FLAG_TC);		
		}
}

// IIC读数据：
//uint8_t i2c_read_byte(unsigned char add){  
////	  uint8_t readByte = 0;
////	  uint8_t ii = I2C_TimeOut;
////	  // 产生起始信号
////		I2C_EnableGenerateStart(IIC2_ID);
////	  // 等待EV5事件：检测起始信号是否成功
////	  while((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_MODE_SELECT)) && ii){
////			  ii--;
////		}    
////		// 发送从设备地址
////	  I2C_Tx7BitAddress(IIC2_ID, OLed_Tx_Addr, I2C_DIRECTION_TX);
////	  // 检测EV6事件：等待从机地址是否发送完;
////		ii = I2C_TimeOut;
////		while ((!I2C_ReadEventStatus(IIC2_ID,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && ii){
////			  ii--;
////		} 	   
////	  // 发送数据寄存器地址：
////		I2C_TxData(IIC2_ID, add); 
////		// 检测EV8_2；等待最后一个字节数据发送完; 
////		ii = I2C_TimeOut;
////	  while ((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) && ii){ 
////			  ii--;
////		} 
////		////////////////////////// 启动读数据系列 ////////////////////////////
////		// 产生起始信号
////		I2C_EnableGenerateStart(IIC2_ID);
////	  // 等待EV5事件：检测起始信号是否成功
////	  while((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_MODE_SELECT)) && ii){  
////			  ii--;
////		}    
////		// 发送从设备地址：读模式
////	  I2C_Tx7BitAddress(IIC2_ID, OLed_Tx_Addr, I2C_DIRECTION_RX);  
////		// 关闭应答
////		I2C_DisableAcknowledge(IIC2_ID); 
////    // 发送停止信号
////		I2C_EnableGenerateStop(IIC2_ID); 
////		// 等待事件EV7:接收数据
////		while((!I2C_ReadEventStatus(IIC2_ID, I2C_EVENT_MASTER_BYTE_RECEIVED)) && ii){  
////			  ii--;  
////		} 
////		readByte = I2C_RxData(IIC2_ID);	  
////		// 开启应答  
////		I2C_EnableAcknowledge(IIC2_ID);  
////    return 	readByte;
//    return 0;
//}

#endif

